'use strict';

import React, { Component } from 'react';
import {
  FlatList, View,
  RefreshControl,
  PanResponder,
  Animated,
  Easing,
  Dimensions,
  ActivityIndicator,
  StyleSheet,
  Text
} from 'react-native';

import Pullable from './Pullable';

/**
 支持android&ios可以下拉刷新的PullList组件
 Demo:
 import {PullList} from 'react-native-pullview';
 <PullList onPulling={} onPullOk={} onPullRelease={} isPullEnd={true}
 topIndicatorRender={({pulling, pullok, pullrelease}) => {}} topIndicatorHeight={60}
 {...ListView.props}
 >
 Demo2:
 topIndicatorRender(pulling, pullok, pullrelease) {
        return <View style={{flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', height: 60}}>
            <ActivityIndicator size="small" color="gray" />
            {pulling ? <Text>下拉刷新2...</Text> : null}
            {pullok ? <Text>松开刷新2......</Text> : null}
            {pullrelease ? <Text>玩命刷新中2......</Text> : null}
        </View>;
    }
 <PullList onPullRelease={this.props.onRefresh} topIndicatorRender={this.topIndicatorRender} topIndicatorHeight={60} {...ListView.props} />
 */
// const padding = 2; //scrollview与外面容器的距离
const pullOkMargin = 100; // 下拉到ok状态时topindicator距离顶部的距离
const defaultDuration = 300;
const defaultTopIndicatorHeight = 60; // 顶部刷新指示器的高度
const defaultFlag = { pulling: false, pullok: false, pullrelease: false };
const flagPulling = { pulling: true, pullok: false, pullrelease: false };
const flagPullok = { pulling: false, pullok: true, pullrelease: false };
const flagPullrelease = { pulling: false, pullok: false, pullrelease: true };
const isDownGesture = (x, y) => {
  return y > 0 && y > Math.abs(x);
};
const isUpGesture = (x, y) => {
  return y < 0 && Math.abs(x) < Math.abs(y);
};
const isVerticalGesture = (x, y) => {
  return Math.abs(x) < Math.abs(y);
};


export default class extends React.Component {
  constructor(props) {
    super(props);
    this.getMetrics = this.getMetrics.bind(this);
    this.scrollToOffset = this.scrollToOffset.bind(this);
    this.scrollToEnd = this.scrollToEnd.bind(this);
    this.listType = 'flat';
    this.topIndicatorHeight =
      defaultTopIndicatorHeight;
    this.defaultXY = { x: 0, y: this.topIndicatorHeight * -1 };
    this.pullOkMargin = pullOkMargin;
    this.duration = defaultDuration;
    this.scrollEnabled = true
    this.scrollY = 0
    this.state = {
      pullPan: new Animated.ValueXY(this.defaultXY),
      flag: defaultFlag,
      height: 0
    }
    this.gesturePosition = { x: 0, y: 0 };
    this.isPullState = this.isPullState.bind(this);
    this.resetDefaultXYHandler = this.resetDefaultXYHandler.bind(this);
    this.setFlag = this.setFlag.bind(this);
    this.renderTopIndicator = this.renderTopIndicator.bind(this);

    this.defaultTopIndicatorRender = this.defaultTopIndicatorRender.bind(this);
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: this.onShouldSetPanResponder.bind(this),
      onMoveShouldSetPanResponder: this.onShouldSetPanResponder.bind(this),
      onPanResponderGrant: () => { },
      onPanResponderMove: this.onPanResponderMove.bind(this),
      onPanResponderRelease: this.onPanResponderRelease.bind(this),
      onPanResponderTerminate: this.onPanResponderRelease.bind(this)
    });
    this.setFlag(defaultFlag);
  }

  renderTopIndicator() {
    let { pulling, pullok, pullrelease } = this.flag;
    if (this.props.topIndicatorRender == null) {
      return this.defaultTopIndicatorRender(pulling, pullok, pullrelease, this.gesturePosition);
    } else {
      return this.props.topIndicatorRender(pulling, pullok, pullrelease, this.gesturePosition);
    }
  }

  defaultTopIndicatorRender(pulling, pullok, pullrelease) {
    const hide = { position: 'absolute', left: 10000 };
    const show = { position: 'relative', left: 0 };
    setTimeout(() => {
      if (this.isPullState()) {
        if (pulling) {
          this.txtPulling && this.txtPulling.setNativeProps({ style: show });
          this.txtPullok && this.txtPullok.setNativeProps({ style: hide });
          this.txtPullrelease && this.txtPullrelease.setNativeProps({ style: hide });
        } else if (pullok) {
          this.txtPulling && this.txtPulling.setNativeProps({ style: hide });
          this.txtPullok && this.txtPullok.setNativeProps({ style: show });
          this.txtPullrelease && this.txtPullrelease.setNativeProps({ style: hide });
        } else if (pullrelease) {
          this.txtPulling && this.txtPulling.setNativeProps({ style: hide });
          this.txtPullok && this.txtPullok.setNativeProps({ style: hide });
          this.txtPullrelease && this.txtPullrelease.setNativeProps({ style: show });
        }
      } else {
        this.txtPulling && this.txtPulling.setNativeProps({ style: show });
        this.txtPullok && this.txtPullok.setNativeProps({ style: hide });
        this.txtPullrelease && this.txtPullrelease.setNativeProps({ style: hide });
      }
    }, 1);
    return (
      <View
        style={{
          flexDirection: 'row',
          justifyContent: 'center',
          alignItems: 'center',
          height: 60,
          zIndex: 1
        }}
      >
        <ActivityIndicator size="small" color="red" />
        <View
          ref={(c) => {
            this.txtPulling = c;
          }}
        >
          <Text style={styles.indicatorText}>{PageTexts.PULLING}</Text>
        </View>
        <View
          ref={(c) => {
            this.txtPullok = c;
          }}
        >
          <Text style={styles.indicatorText}>{PageTexts.PULL_OK}</Text>
        </View>
        <View
          ref={(c) => {
            this.txtPullrelease = c;
          }}
        >
          <Text style={styles.indicatorText}>{PageTexts.PULL_RELEASE}</Text>
        </View>
      </View>
    );
  }

  getMetrics(args) {
    this.scroll.getMetrics(args);
  }

  scrollToOffset(...args) {
    this.scroll.scrollToOffset(...args);
  }

  scrollToEnd(args) {
    this.scroll.scrollToEnd(args);
  }

  onShouldSetPanResponder = (e, gesture) => {
    if (!isVerticalGesture(gesture.dx, gesture.dy)) {
      // 不使用pullable,或非向上 或向下手势不响应
      return false;
    }
    // if (this.props.onPulling || this.props.onPullOk || this.props.onPullRelease) {
    //     return !this.state.scrollEnabled;
    // }
    if (this.scrollY <= 0 && isDownGesture(gesture.dx, gesture.dy)) {
      this.scroll.setNativeProps({
        scrollEnabled: false
      })
      this.scrollEnabled = false
      this.lastY = this.state.pullPan.y._value;
      return true;
    } else if (isUpGesture(gesture.dx, gesture.dy)) {
      if (!this.scrollEnabled) {
        this.scroll.setNativeProps({
          scrollEnabled: true
        })
        this.scrollEnabled = true
        this.scroll.scrollToOffset({ offset: -gesture.dy, animated: false })
      }
      return false;
    }
    return false
    // if (!this.scrollEnabled && (!this.isPullState()) && isUpGesture(gesture.dx, gesture.dy)) {
    //   this.scroll.setNativeProps({
    //     scrollEnabled: true
    //   })
    //   this.scrollEnabled = true
    //   this.scroll.scrollToOffset({ offset: -gesture.dy, animated: false })
    //   return false;
    // }
  }

  onPanResponderMove(e, gesture) {
    this.gesturePosition = { x: this.defaultXY.x, y: gesture.dy };
    if (isUpGesture(gesture.dx, gesture.dy)) {
      // 向上滑动
      if (this.isPullState()) {
        this.resetDefaultXYHandler();
      } else if (this.props.onPushing && this.props.onPushing(this.gesturePosition)) {
        // do nothing, handling by this.props.onPushing
      } else {

      }
      return;
    } else if (isDownGesture(gesture.dx, gesture.dy)) {
      // 下拉
      this.state.pullPan.setValue({ x: this.defaultXY.x, y: this.lastY + gesture.dy / 2 });
      if (gesture.dy < this.topIndicatorHeight + this.pullOkMargin) {
        // 正在下拉
        if (!this.flag.pulling) {
          this.props.onPulling && this.props.onPulling();
        }
        this.setFlag(flagPulling);
      } else {
        // 下拉到位
        if (!this.state.pullok) {
          this.props.onPullOk && this.props.onPullOk();
        }
        this.setFlag(flagPullok);
      }
    }
  }

  onLayout = (e) => {
    if (
      this.state.height != e.nativeEvent.layout.height
    ) {
      this.scroll.setNativeProps({
        style: { width: e.nativeEvent.layout.width, height: e.nativeEvent.layout.height }
      });
      this.setState({
        height: e.nativeEvent.layout.height
      })
    }
  }


  onPanResponderRelease(e, gesture) {
    if (this.flag.pulling) {
      // 没有下拉到位
      this.resetDefaultXYHandler(); // 重置状态
    }
    if (this.flag.pullok) {
      if (!this.flag.pullrelease) {
        if (this.props.onPullRelease) {
          this.props.onPullRelease();
        } else {
          setTimeout(() => {
            this.resetDefaultXYHandler();
          }, 3000);
        }
      }
      this.setFlag(flagPullrelease); // 完成下拉，已松开
      Animated.timing(this.state.pullPan, {
        toValue: { x: 0, y: 0 },
        easing: Easing.linear,
        duration: this.duration
      }).start();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.isRefreshing !== this.props.isRefreshing && !nextProps.isRefreshing) {
      this.resetDefaultXYHandler();
    }
  }

  isPullState() {
    return this.flag.pulling || this.flag.pullok || this.flag.pullrelease;
  }

  setFlag(flag) {
    if (this.flag != flag) {
      this.flag = flag;
      this.renderTopIndicator();
    }
  }
  resetDefaultXYHandler() {
    this.flag = defaultFlag;
    this.state.pullPan.setValue(this.defaultXY);
    if (!this.scrollEnabled) {
      this.scroll.setNativeProps({
        scrollEnabled: true
      })
      this.scrollEnabled = true
    }
  }

  onScroll = (e) => {
    this.scrollY = e.nativeEvent.contentOffset.y
    return;
    if (e.nativeEvent.contentOffset.y <= 0) {
      this.scrollEnabled = false
      this.scroll.setNativeProps({ scrollEnabled: false });
      setTimeout(() => {
        this.scrollEnabled = true
        this.scroll.setNativeProps({ scrollEnabled: true });
      }, 1200);
    } else if (!this.isPullState()) {
      this.scrollEnabled = true
      this.scroll.setNativeProps({ scrollEnabled: true });
    }
  }

  render() {
    return (
      <View
      {...this.panResponder.panHandlers}

        style={{
          flex: 1,
          flexGrow: 1,
          flexDirection: 'column',
          zIndex: -999
        }} onLayout={this.onLayout}
      >

        <Animated.View
          ref={(c) => {
            this.ani = c;
          }}
          style={[this.state.pullPan.getLayout()]}>
          {this.renderTopIndicator()}

          <FlatList
            refreshControl={null}
            ref={(c) => {
              this.scroll = c;
            }}
            style={{ height: this.state.height }}
            scrollEnabled={this.scrollEnabled}
            onScroll={this.onScroll}
            {...this.props}
          />

        </Animated.View>
      </View>

    );
  }
}

const styles = StyleSheet.create({
  wrap: {
    flex: 1,
    flexGrow: 1,
    flexDirection: 'column',
    zIndex: -999
  },
  hide: {
    position: 'absolute',
    left: 10000
  },
  show: {
    position: 'relative',
    left: 0
  },
  indicatorText: {
    fontSize: 25,
    marginLeft: 20
  }
});
